package com.ocelot.san.controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.PhaseId;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.icefaces.ace.event.RowEditEvent;
import org.icefaces.util.JavaScriptRunner;

import com.icesoft.faces.component.ext.RowSelectorEvent;
import com.icesoft.faces.component.paneltabset.TabChangeEvent;
import com.ocelot.san.dto.Balance;
import com.ocelot.san.dto.Client;
import com.ocelot.san.dto.Operation;
import com.ocelot.san.exception.ServiceException;
import com.ocelot.san.form.ClientForm;
import com.ocelot.san.form.OperationForm;
import com.ocelot.san.service.BalanceService;
import com.ocelot.san.service.ClientService;
import com.ocelot.san.service.OperationService;
import com.ocelot.san.type.SegmentType;
import com.ocelot.san.utils.FacesUtils;

@ManagedBean(name = "operationController")
@ViewScoped
public class OperationController implements Serializable {

	private static final long serialVersionUID = -8758711089368514347L;

	@ManagedProperty(value = "#{operationService}")
	private OperationService operationService;

	@ManagedProperty(value = "#{clientService}")
	private ClientService clientService;
	
	@ManagedProperty(value = "#{balanceService}")
	private BalanceService balanceService;


	private ClientForm clientForm;

	private OperationForm operationForm;

	@PostConstruct
	public void loadData() {
		
		clientForm = new ClientForm();
		operationForm = new OperationForm();
		
		operationForm.setLawyers(operationService.fetchAllLawyers());
		operationForm.setNotaries(operationService.fetchAllNotaries());
		operationForm.setOperationTypes(operationService.fetchAllOperationTypes());
		clientForm.setClients(clientService.findAll());
		operationForm.setOperation(getOperation());
	}
	
	
	public void processTabChange(TabChangeEvent e)  {
		
		int tabIndex = e.getNewTabIndex();
		switch (tabIndex) {
			case 1:loadFeeData();break;
		}
		
	}
	
	public void loadFeeData()  {
		try {
			Long operationId = operationForm.getOperation().getId();
			if(operationId!=null) {
				List<Balance> balances = balanceService.loadDefaultConcepts(operationId, SegmentType.EXPENSE);
				operationForm.setBalances(balances);
				updateTotalBalances(balances);
			}
		} catch (ServiceException e) {
			e.printStackTrace();
		}
	}
	
	public void updateTotalBalances(List<Balance> balances) {
		Balance totalBalance = new Balance();
		if(CollectionUtils.isNotEmpty(balances)) {
			for(Balance balance : balances) {
				totalBalance.setAmount(totalBalance.getAmount() + balance.getAmount());
				totalBalance.setBalance(totalBalance.getBalance() + balance.getBalance());
				totalBalance.setDeposit(totalBalance.getDeposit() + balance.getDeposit());
			}
		}
		operationForm.setTotalBalance(totalBalance);
	}
	
	public void updateBalanceValues(RowEditEvent event) {

			PhaseId phaseId = event.getPhaseId();
			
			if(PhaseId.ANY_PHASE.equals(phaseId)){
				event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
				event.queue();
				Balance balance = (Balance) event.getObject();
				balance.setBalance(balance.getAmount() - balance.getDeposit());
			} else if(PhaseId.UPDATE_MODEL_VALUES.equals(phaseId)) {
				System.out.println("phaseId:" + phaseId);
				List<Balance> balances = operationForm.getBalances();
				updateTotalBalances(balances);
			}
			
	}
	
	public Operation getOperation() {
		Operation operation = new Operation(); 
		Object obj  = getSelectedOperationIdFromSession();
		 if(obj!=null) {
			 Long id = (Long) obj;
			 operation = operationService.findOperationById(id);
			 removeOperationIdFromSession();
		 }
		 return operation;
	}

	protected void removeOperationIdFromSession() {
		FacesUtils.getInstance().removeManagedBeanInSession("SELECTED_OPERATION_ID");
	}

	protected Object getSelectedOperationIdFromSession() {
		return FacesUtils.getInstance().getManagedBeanInSession("SELECTED_OPERATION_ID");
	}
	
	public String closeFolioDialog() {
		JavaScriptRunner.runScript(FacesContext.getCurrentInstance(),"operationFolioDialog.hide();");	
		return "operationUpdate";
	}
	
	public void showClientDialog(ActionEvent  event) {
		
		JavaScriptRunner.runScript(FacesContext.getCurrentInstance(),"clientDialog.show();");
		
	}
	
	public void closeClientDialog() {
		
		JavaScriptRunner.runScript(FacesContext.getCurrentInstance(),"clientDialog.hide();");
		
	}

	public void submitClient(ActionEvent event) {
		if(validateClientForm()) {
			clientService.save(clientForm.getEditClient());
			// clear Data
			clientForm.setEditClient(new Client());
			refreshClientList();
		}
	}

	public void selectClient(RowSelectorEvent event) {
		PhaseId phaseId = event.getPhaseId();
		if (PhaseId.APPLY_REQUEST_VALUES.equals(phaseId)) {
			event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
			event.queue();
			closeClientDialog();
		} else if (PhaseId.UPDATE_MODEL_VALUES.equals(phaseId)) {
			operationForm.getOperation().setClient(clientForm.getClients().get(
					event.getRow()));
		}
	}

	public String editItem() {
		Long idToEdit = clientForm.getToEdit();
		Client toModify = getClientById(idToEdit);
		clientForm.setEditClient(toModify);
		return null;
	}

	public String removeItem() {
		Long indexToRemove = clientForm.getToRemove();
		Client removeCar = getClientById(indexToRemove);
		if (removeCar != null) {
			clientService.delete(removeCar.getId());
			clientForm.getClients().remove(removeCar);
			clientForm.setEditClient(new Client());
			refreshClientList();
		}
		return null;
	}
	
	
	public String submitOperation() {
		if(validateOperationForm()) {
			boolean showDialog = operationForm.getOperation().getId()==null;
				operationForm.getOperation().setDate(Calendar.getInstance());
				operationService.save(operationForm.getOperation());
				if(showDialog) {
					JavaScriptRunner.runScript(FacesContext.getCurrentInstance(),
						"operationFolioDialog.show();");
				} else {
					return "operationUpdate";
				}
		}
		return "";
	}

	public boolean validateOperationForm() {
		List<String> errors = new ArrayList<String>();
		if(operationForm.getOperation().getClient()==null) {
			errors.add("Es necesario seleccionar un cliente");
		}
		if(operationForm.getOperation().getNotary()==null) {
			errors.add("Es necesario seleccionar un notario");
		}
		if(operationForm.getOperation().getLawyer()==null) {
			errors.add("Es necesario seleccionar un abogado");
		}
		if(operationForm.getOperation().getOperationType()==null){
			errors.add("Es necesario seleccionar una operacion");
		}
		if(errors.size() > 0) {
			for(String error:errors){
				 FacesMessage message=new FacesMessage(error);  
				 message.setSeverity(FacesMessage.SEVERITY_INFO);  
				 FacesContext ctx= FacesContext.getCurrentInstance();  
				 ctx.addMessage("operationForm", message);
			}
			return false;
		}
		return true;
	}
	
	
	public boolean validateClientForm() {
		List<String> errors = new ArrayList<String>();
		
		if(StringUtils.isEmpty(clientForm.getEditClient().getName())) {
			errors.add("El nombre es requerido");
		}
		if(StringUtils.isEmpty(clientForm.getEditClient().getPhone())) {
			errors.add("El teléfono es requerido");
		}
		if(StringUtils.isEmpty(clientForm.getEditClient().getAddress())) {
			errors.add("La direccion es requerida");
		}
		if(errors.size() > 0) {
			for(String error:errors){
				 FacesMessage message=new FacesMessage(error);  
				 message.setSeverity(FacesMessage.SEVERITY_INFO);  
				 FacesContext ctx= FacesContext.getCurrentInstance();  
				 ctx.addMessage("clientForm", message);
			}
			return false;
		}
		return true;
	}
	
	
	public String closeOperationDlg() {
		return "operationUpdate";
	}
	
	
	protected void refreshClientList() {
		clientForm.setClients(clientService.findAll());
	}

	private Client getClientById(Long id) {
		return clientService.findById(id);
	}

	public void setClientService(ClientService clientService) {
		this.clientService = clientService;
	}

	public void setClientForm(ClientForm clientForm) {
		this.clientForm = clientForm;
	}

	public OperationService getOperationService() {
		return operationService;
	}

	public void setOperationService(OperationService operationService) {
		this.operationService = operationService;
	}

	public OperationForm getOperationForm() {
		return operationForm;
	}

	public void setOperationForm(OperationForm operationForm) {
		this.operationForm = operationForm;
	}

	public ClientService getClientService() {
		return clientService;
	}

	public ClientForm getClientForm() {
		return clientForm;
	}


	public BalanceService getBalanceService() {
		return balanceService;
	}


	public void setBalanceService(BalanceService balanceService) {
		this.balanceService = balanceService;
	}
}
